#include <rtthread.h>
#include <sys/time.h>
#include "os_evt.h"

#include "app_dbg_sm.h"
#include "app_dbg_mp.h"
#include "app_dbg_util.h"
#include "app_dbg_cmd.h"
#include "app_dbg_drv.h"

#define LOG_TAG        "dbg.sm"
#define LOG_LVL         LOG_LVL_DBG
#include "ulog.h"

#define DBG_SM_OVER_TIME   (30)   //产测超时时间

typedef struct
{ 
    UINT8 curr_mod;      //当前模式
    UINT32 time;         //计时
    UINT8 val;           //数值

    UINT8 u_up_type;     //上报的cmd类型
    UINT8 u_retry;       //重发计数
    UINT8 chk_cnt;       //检验项计时

}app_dbg_sm_info_t;

static app_dbg_sm_info_t app_dbg_sm_info = {0};

static UINT8 app_dbg_idle(UINT8 evt, void *pt_buffer);
static UINT8 app_dbg_conn(UINT8 evt, void *pt_buffer);
static UINT8 app_dbg_up(UINT8 evt, void *pt_buffer);
static UINT8 app_dbg_disconn(UINT8 evt, void *pt_buffer);

//状态对应功能表
static const os_evt_tab_t app_dbg_sm_tab[APP_DBG_SM_MOD_MAX] = 
{
    {"DBG_IDLE",     app_dbg_idle     },       
    {"DBG_CONN",     app_dbg_conn     },     
    {"DBG_UP",       app_dbg_up       },    
    {"DBG_DISCONN",  app_dbg_disconn  }, 
};

struct os_evt_param dbg_evt = {0};

//状态机事件驱动
void app_dbg_sm_evt_proc(app_dbg_sm_evt_e evt, void *pt_buffer)
{
    os_evt_proc(&dbg_evt, (UINT8)evt, pt_buffer);
}

//状态机初始化
void app_dbg_sm_init()
{
    memset(&app_dbg_sm_info, 0, sizeof(app_dbg_sm_info_t));

    os_evt_init(&dbg_evt, "dbg_sm", app_dbg_sm_tab, APP_DBG_SM_MOD_IDLE, APP_DBG_SM_MOD_MAX, APP_DBG_SM_EVT_MAX);
    app_dbg_sm_evt_proc(APP_DBG_SM_EVT_INIT, NULL);
}

//清除心跳计时
void app_dbg_sm_heart_time_clr()
{
    if(app_dbg_conn_flag_get()){
        app_dbg_sm_info.time = 0;
        app_dbg_up_flag_clr(APP_DBG_SM_UP_HEART); 
    }
}

/************************************************************************
空闲状态

************************************************************************/
static UINT8 app_dbg_idle(UINT8 evt, void *pt_buffer)
{
    app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_IDLE;
    UINT8 *ptem = (UINT8 *)pt_buffer;
    UINT8 chr = 0;
  
    switch (evt)
    {
    case APP_DBG_SM_EVT_INIT:
        app_dbg_sm_info.time = 0;

    break;

    case APP_DBG_SM_EVT_TIMER:
        app_dbg_sm_info.time++;
        if(FALSE == app_dbg_conn_flag_get()){    //未连接   
            break;
        }
        if( app_dbg_drv_item_get()&&(app_dbg_sm_info.time >= DBG_SM_OVER_TIME) ){ //超时
            app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_DISCONN; 
            app_dbg_sm_info.val = DBG_VAL_OVERTIME; //超时关闭
            break;
        }
        app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_CONN;
        app_dbg_sm_info.chk_cnt = 0; 
    break;   

    case APP_DBG_SM_EVT_DISCONN:   
        app_dbg_sm_info.val = *ptem;
        app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_DISCONN;  //跳到关闭状态
    break;    
        
    default:
        if (evt > APP_DBG_SM_EVT_MAX){
            //log_w("app_dbg_idle(evt=%d)",evt);
        }        
    break;   
    }

    return app_dbg_sm_info.curr_mod;
}

/************************************************************************
连接

************************************************************************/
static UINT8 app_dbg_conn(UINT8 evt, void *pt_buffer)
{
    app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_CONN;
    UINT8 *ptem = (UINT8 *)pt_buffer;
    UINT8 i;
    INT8 flag;

    switch (evt)
    {
    case APP_DBG_SM_EVT_INIT:
        app_dbg_sm_info.time = 0;          
    break;

    case APP_DBG_SM_EVT_TIMER:
        app_dbg_sm_info.time++;
        app_dbg_sm_info.chk_cnt++; 
        if( app_dbg_drv_item_get()&&(app_dbg_sm_info.chk_cnt >= DBG_SM_OVER_TIME) ){ //超时
            app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_DISCONN; 
            app_dbg_sm_info.val = DBG_VAL_OVERTIME; //超时关闭
            break;
        }

        for(i = 0; i < APP_DBG_SM_UP_MAX; i++){
            flag = app_dbg_up_flag_get(i);
            if(flag >= 0)
            {//获取到上报标志
                app_dbg_sm_info.u_up_type = flag;
                app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_UP;
                break;
            }
        }
        if( app_dbg_sm_info.time == 3){
            app_dbg_up_flag_set(APP_DBG_SM_UP_HEART); //心跳
        }

    break; 

    case APP_DBG_SM_EVT_DISCONN:   
        app_dbg_sm_info.val = *ptem;
        app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_DISCONN;  //跳到关闭状态
    break;    
  

    default:
        if (evt > APP_DBG_SM_EVT_MAX){
            //log_w("app_tool_online(evt=%d)",evt);
        }       
    break;   
    }

    return app_dbg_sm_info.curr_mod;
}

/************************************************************************
上报

************************************************************************/
static UINT8 app_dbg_up(UINT8 evt, void *pt_buffer)
{
    app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_UP;
    UINT8 *ptem = (UINT8 *)pt_buffer;

    switch (evt)
    {
    case APP_DBG_SM_EVT_INIT:
        app_dbg_sm_info.time = 0;
        app_dbg_sm_info.u_retry = 0; //重发次数清零
        app_dbg_drv_pkg_send(DBG_CMD_HEART, NULL, 0); 
    break;

    case APP_DBG_SM_EVT_TIMER:
        app_dbg_sm_info.time++;        
        app_dbg_sm_info.chk_cnt++;   
        if (app_dbg_sm_info.u_retry >= 3){
            app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_DISCONN;
            break;
        }

        if (app_dbg_sm_info.time >= 3){ //3秒无响应后发布超时
            app_dbg_sm_info.time=0;
            app_dbg_sm_info.u_retry++;
            app_dbg_drv_pkg_send(DBG_CMD_HEART, NULL, 0);  //重新发送
        }
    break;   


    case APP_DBG_SM_EVT_UP_OK:
        app_dbg_up_flag_clr(app_dbg_sm_info.u_up_type); //清除上报标志
        app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_CONN;   //跳到连接状态
    break;   

    case APP_DBG_SM_EVT_DISCONN:   
        app_dbg_sm_info.val = *ptem;
        app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_DISCONN;  //跳到关闭状态
    break;    

    default:
        if (evt > APP_DBG_SM_EVT_MAX){
            //log_w("app_dbg_disconn(evt=%d)",evt);
        }        
    break;   
    }

    return app_dbg_sm_info.curr_mod;
}


/************************************************************************
断开连接

************************************************************************/
static UINT8 app_dbg_disconn(UINT8 evt, void *pt_buffer)
{
    app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_DISCONN;
    UINT8 *ptem = (UINT8 *)pt_buffer;

    switch (evt)
    {
    case APP_DBG_SM_EVT_INIT:
        app_dbg_sm_info.time = 0;
        app_dbg_up_flag_clr(app_dbg_sm_info.u_up_type); //清除上报标志
        app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_IDLE;  //跳到空闲状态   
        app_dbg_drv_pkg_send_char(DBG_CMD_DISCONN, app_dbg_sm_info.val);    
        app_dbg_drv_disconnect(); //关闭连接   
    break;

    case APP_DBG_SM_EVT_TIMER:
        app_dbg_sm_info.time++;
        if(app_dbg_sm_info.time > 1){
            app_dbg_sm_info.curr_mod = APP_DBG_SM_MOD_IDLE;  //跳到空闲状态  
            break;
        }
    break;   

    default:
        if (evt > APP_DBG_SM_EVT_MAX){
            //log_w("app_dbg_disconn(evt=%d)",evt);
        }        
    break;   
    }

    return app_dbg_sm_info.curr_mod;
}

//============================================

static UINT32 upflag = 0;   //上报状态位

//设置上报位
void app_dbg_up_flag_set(app_dbg_sm_up_e e_up)
{
    upflag |= (1 << e_up);
}

//清除上报位
void app_dbg_up_flag_clr(app_dbg_sm_up_e e_up)
{
    upflag &= ~(1 << e_up);
}

//获取上报位
INT8 app_dbg_up_flag_get()
{
    INT8 i;
    for (i = 0; i < APP_DBG_SM_UP_MAX; i++) {
        if (upflag & (1 << i)){
            return i;
        }
    }
    return -1;
}





